package code17_reflect;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class TestField {

	public static void main(String[] args) throws Exception {
		//f1();
		
		
		f2();
	}

	private static void f2() throws Exception {
		Class<?> c = Stu.class;
		
		// 准备用于访问属性时需要的对象
		Object stu = c.newInstance();
		
		Field f = c.getDeclaredField("age");
		
		// 如果属性是私有的, 如果任然需要强制访问, 则需要设置 允许访问
		// 只对当前的 Field对象有效
		f.setAccessible(true);// 一般被称为破坏封装
		
		// 如果访问的属性是 静态的, 则不需要传入对象, 传入 null
		
		// 赋值
		// 正常的访问: 对象.属性名 = 值
		try {
			// 反射的操作: 设置指定对象的该属性的值
			f.set(stu, 20);
		} catch (IllegalArgumentException e) {
			// 参数类型错误
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// 无法直接访问, 修饰符问题
			e.printStackTrace();
		}
		
		// 取值
		// 正常的访问: 变量 = 对象.属性名
		// 反射操作: 获取指定对象的该属性值
		Object value = f.get(stu);
		
		// 需要使用对应的类型则需要强制转换
		Integer age = (Integer) value;
		System.out.println("age:" + age);
		
	}

	private static void f1() {
		Class<?> c = Stu.class;
		
		// 1. 获取 当前类 以及 其超类 中所有 public 修饰的属性
		Field[] fields = c.getFields();
		
		// 2. 获取 当前类中 所有属性 (含 private)
		fields = c.getDeclaredFields();
		
		for (Field f : fields) {
			// 获取属性的 修饰符、类型、名称
			int modifiers = f.getModifiers();
			System.out.print(Modifier.toString(modifiers));
			System.out.print(" ");
			
			Class<?> fieldType = f.getType();
			System.out.print(fieldType.getName());
			System.out.print(" ");
			
			String name = f.getName();
			System.out.println(name);
		}
		System.out.println("-----------------");
		
		try {
			// 3.根据属性名 获取 当前类 以及 其超类 中对应的  public 修饰的属性(同名属性, 只能获取到自己的)
			Field f = c.getField("name");
			System.out.println("name : " + f);
		} catch (NoSuchFieldException e) {
			// 没有该属性 或 属性不是public 修饰的
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		}
		
		try {
			// 4. 根据属性名 获取 当前类中 指定属性 (含 private)
			Field f = c.getDeclaredField("age");
			System.out.println("age : " + f);
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		}
	}
}
